package main

// GOOS=linux GOARCH=amd64 go build -o backup
import (
	"database/sql"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/robfig/cron/v3"
	"gopkg.in/yaml.v2"
)

var (
	// MySQL数据库连接信息
	dbUser,
	dbPass,
	dbHost,
	dbPort,
	dbName,
	// mysql 容器名称或ID
	mysqlContainer,

	// 备份文件路径
	backupPath,
	// 保留的备份文件数量
	backupCount,
	// 定义备份时间
	backupTime string
)

type Config struct {
	Database struct {
		Name           string `yaml:"name"`
		Host           string `yaml:"host"`
		Port           int    `yaml:"port"`
		Username       string `yaml:"username"`
		Password       string `yaml:"password"`
		MysqlContainer string `yaml:"mysqlContainer"`
		BackupPath     string `yaml:"backupPath"`
		BackupCount    string `yaml:"backupCount"`
		BackupTime     string `yaml:"backupTime"`
	} `yaml:"database"`
}

func main() {
	// 读取YAML文件
	data, err := ioutil.ReadFile("./config/config.yaml")
	if err != nil {
		log.Fatalf("error: %v", err)
	}

	// 解析YAML数据
	var config Config
	err = yaml.Unmarshal(data, &config)
	if err != nil {
		log.Fatalf("error: %v", err)
	}

	// 打印配置信息
	dbUser = config.Database.Username
	dbPass = config.Database.Password
	dbHost = config.Database.Host
	dbPort = fmt.Sprintf("%d", config.Database.Port)
	dbName = config.Database.Name
	mysqlContainer = config.Database.MysqlContainer
	backupPath = config.Database.BackupPath
	backupCount = config.Database.BackupCount
	backupTime = config.Database.BackupTime

	fmt.Println("备份程序启动")
	// 执行getReady.sh脚本，准备备份文件路径
	delCmd := exec.Command("bash", "-c", "./getReady.sh "+backupPath)
	delCmd.Stdout = os.Stdout
	delCmd.Stderr = os.Stderr
	err = delCmd.Run()
	if err != nil {
		fmt.Println("Error:", err)
	}
	fmt.Println("准备工作完成")
	// 连接数据库
	fmt.Println("连接数据库")
	fmt.Println("dbUser:", dbUser)
	fmt.Println("dbPass:", dbPass)
	fmt.Println("dbHost:", dbHost)
	fmt.Println("dbPort:", dbPort)
	fmt.Println("dbName:", dbName)
	db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", dbUser, dbPass, dbHost, dbPort, dbName))
	fmt.Println("sql.Open")
	if err != nil {
		fmt.Println(err)
		log.Fatal(err)
	}
	fmt.Println("defer db.Close()")
	defer db.Close()
	fmt.Println("检查数据库连接")

	// 检查数据库连接
	err = db.Ping()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("检查数据库连接成功")
	fmt.Println("测试备份")
	err = backupDatabase(db)
	if err != nil {
		log.Println("数据库备份失败:", err)
	} else {
		fmt.Println("数据库备份成功")
	}
	fmt.Println("开启定时任务")
	c := cron.New()
	// 每天凌晨2点执行
	_, err = c.AddFunc(backupTime, func() {
		err := backupDatabase(db)
		if err != nil {
			log.Println("数据库备份失败:", err)
		} else {
			fmt.Println("数据库备份成功")
		}
	})
	if err != nil {
		fmt.Println("定时任务报错:", err)
	}
	c.Start()

	select {}
}

func backupDatabase(db *sql.DB) error {
	// 创建备份文件名
	fmt.Println("创建备份文件名")
	timestamp := time.Now().Format("20060102150405")
	backupFile := fmt.Sprintf("backup_%s.sql", timestamp)
	// 执行mysqldump命令进行备份
	fmt.Println("执行mysqldump命令进行备份")
	fmt.Println("sh ./backup.sh " + backupFile)
	cmd := exec.Command("bash", "-c", "./backup.sh "+backupFile+" "+dbUser+" "+dbPass+" "+dbHost+" "+dbPort+" "+dbName+" "+mysqlContainer+" "+backupPath)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		fmt.Println("Error:", err)
	}
	// 执行delsql.sh脚本，删除多余的备份文件
	delCmd := exec.Command("bash", "-c", "./delsql.sh "+backupPath+" "+backupCount)
	delCmd.Stdout = os.Stdout
	delCmd.Stderr = os.Stderr
	err = delCmd.Run()
	if err != nil {
		fmt.Println("Error:", err)
	}
	fmt.Printf("数据库备份已保存到 %s\n", backupFile)

	return nil
}
